package me.yidasanqian.crowdfunding.app;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import me.yidasanqian.crowdfunding.domain.Jwt;
import me.yidasanqian.crowdfunding.domain.User;
import me.yidasanqian.crowdfunding.domain.UserAuthc;
import me.yidasanqian.crowdfunding.service.IJwtService;
import me.yidasanqian.crowdfunding.service.IMediaService;
import me.yidasanqian.crowdfunding.service.IUserAuthcService;
import me.yidasanqian.crowdfunding.service.IUserService;
import me.yidasanqian.crowdfunding.util.JwtUtils;
import me.yidasanqian.crowdfunding.vo.ResultModel;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.*;

/**
 * @author Linyu Chen
 */
@RestController
@RequestMapping("api/v1/user_authc")
public class UserAuthcApi {

    private static final String SESSION_CAPTCHA_KEY = "captcha";
    private static final String URI_SEND_SMS = "https://sms.yunpian.com/v2/sms/single_send.json";

    private final Logger log = LoggerFactory.getLogger(getClass());

    @Resource
    private IUserAuthcService userAuthcService;

    @Resource
    private IUserService userService;

    @Resource
    private IMediaService mediaService;

    @Resource
    private IJwtService jwtService;

    @RequestMapping(value = "fetchCaptcha", method = RequestMethod.GET)
    public Object fetchCaptcha(@RequestParam("tel") String mobile, HttpSession session) {
        String captcha = generateCaptcha();
        // todo 所有用户是否会共享session中同一key的内容？
        session.setAttribute(SESSION_CAPTCHA_KEY, captcha);
        String text = "【阿基米】您的验证码是" + captcha;
        Map<String, String> params = new HashMap<String, String>();
        params.put("apikey", "4c6250dae5d069ca0c308d2dde4f5789");
        params.put("text", text);
        params.put("mobile", mobile);
        String responseText = post(URI_SEND_SMS, params);

        Gson gson = new GsonBuilder().setLenient().create();
        JsonObject jsonObject = gson.fromJson(responseText, JsonObject.class);
        int code = jsonObject.get("code").getAsInt();
        String message = jsonObject.get("msg").getAsString();
        log.debug("responseText ==> " + responseText);
        if (code != 0) {
            return ResultModel.fail(code, message);
        } else {
            return ResultModel.success(responseText);
        }
    }

    @RequestMapping(value = "register", method = RequestMethod.POST)
    public Object register(UserAuthc userAuthc, HttpServletRequest request, HttpSession session) {
        if (userAuthc != null) {
            String persistIdentify = userAuthcService.getIdentifier(userAuthc.getIdentifier());
            if (!StringUtils.isEmpty(persistIdentify)) {
                return ResultModel.fail(1002, "该账号已被注册");
            }
            // TODO 2017/9/30 15:23 验证码
            //String captcha = String.valueOf(session.getAttribute(SESSION_CAPTCHA_KEY));
            String captcha = "1234";
            // 校验通过
            if (!StringUtils.isEmpty(userAuthc.getSmsCode()) && userAuthc.getSmsCode().equals(captcha)) {
                String defaultAvatarUrl = "image/default_avatar.png";
                userAuthcService.registerUser(userAuthc, defaultAvatarUrl);
                session.removeAttribute(SESSION_CAPTCHA_KEY);
                return ResultModel.success();
            } else {
                return ResultModel.fail(1001, "验证码无效");
            }

        } else {
           return ResultModel.fail(1000, "注册信息非法");
        }
    }

    /**
     * 用户用密码登录成功后，服务器返回token给客户端；
     客户端将token保存在本地，发起后续的相关请求时，将token发回给服务器；
     服务器检查token的有效性，有效则返回数据，若无效，分两种情况：
     token错误，这时需要用户重新登录，获取正确的token
     token过期，这时客户端需要再发起一次认证请求，获取新的token
     * @param username
     * @param password
     * @return
     */
    @RequestMapping(value = "login", method = RequestMethod.POST)
    public Object login(@RequestParam("username") String username,
                        @RequestParam("password")String password) {
        String identifier = userAuthcService.getIdentifier(username);
        if (StringUtils.isEmpty(identifier)) {
            return ResultModel.fail(1016, "该账号未注册");
        }

        UserAuthc userAuthc = userAuthcService.getUserAuthc(username, password);
        // 登录成功,过期时间30天
        if (userAuthc != null) {
            String token = JwtUtils.createJWT(username, 2592000000L, "beihai");
            log.debug("login token ==> " + token);

            Long userId = userService.getUserId(userAuthc.getId());

            Jwt jwt = jwtService.getByUserId(userId);
            if (jwt == null) {
                jwt = new Jwt();
                jwt.setUserId(userId);
                jwt.setToken(token);
                //jwt.setCreateTime(new Date());
                jwtService.save(jwt);
            } else {
                jwt.setToken(token);
                //jwt.setUpdateTime(new Date());
                jwtService.update(jwt);
            }

            User user = userService.selectByPrimaryKey(Long.valueOf(userId));
            Map<String, Object> map = new LinkedHashMap<String, Object>();
            map.put("userId", userId);
            map.put("user", user);
            map.put("token", token);
            return ResultModel.success(map);
        } else {
            return ResultModel.fail(1003, "用户名或密码错误");
        }
    }


    @RequestMapping(value = "forgetPassword", method = RequestMethod.POST)
    public Object forgetPassword(@RequestParam("tel")String tel,
                                 @RequestParam("newPassword")String newPassword,
                                 @RequestParam("captcha")String captcha,
                                 HttpSession session) {
        String captchaSession = String.valueOf(session.getAttribute(SESSION_CAPTCHA_KEY));
        if (StringUtils.isEmpty(captcha) || !captcha.equals(captchaSession)) {
            return ResultModel.fail(1001, "验证码无效");
        }

        UserAuthc userAuthc = userAuthcService.getUserAuthc(tel);
        if (userAuthc != null) {
            userAuthc.setCredential(newPassword);
            session.removeAttribute(SESSION_CAPTCHA_KEY);
            return ResultModel.success();
        } else {
            return ResultModel.fail(1008, "该账号不存在");
        }
    }

    private String generateCaptcha() {
        Random random = new Random();
        int value[] = {random.nextInt(9), random.nextInt(9),
                random.nextInt(9), random.nextInt(9)};

        StringBuffer captcha = new StringBuffer();
        for (int i = 0; i < value.length; i++) {
            captcha.append(value[i]);
        }

        return captcha.toString();
    }

    private String post(String url, Map<String, String> paramsMap) {
        CloseableHttpClient client = HttpClients.createDefault();
        String responseText = "";
        CloseableHttpResponse response = null;
        try {
            HttpPost method = new HttpPost(url);
            if (paramsMap != null) {
                List<NameValuePair> paramList = new ArrayList<NameValuePair>();
                for (Map.Entry<String, String> param : paramsMap.entrySet()) {
                    NameValuePair pair = new BasicNameValuePair(param.getKey(), param.getValue());
                    paramList.add(pair);
                }
                method.setEntity(new UrlEncodedFormEntity(paramList, "UTF-8"));
            }
            response = client.execute(method);
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                responseText = EntityUtils.toString(entity);
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        } finally {
            try {
                if (response != null) {
                    response.close();
                }
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
        }
        return responseText;
    }
}
